package com.cn.algorithm.one.map;

import java.util.Objects;

public class LinkedHashMap<K, V> extends HashMap<K, V> {

    LinkedNode<K, V> first;

    LinkedNode<K, V> last;

    @Override
    public void clear() {
        super.clear();
        first = null;
        last = null;
    }

    @Override
    public boolean containsValue(V value) {
        LinkedNode<K, V> node = first;
        while (node != null) {
            if (Objects.equals(value, node.value)) {
                return true;
            }
            node = node.next;
        }
        return false;
    }

    @Override
    public void traversal(VisitMap<K, V> visit) {
        if (visit == null) {
            return;
        }
        LinkedNode<K, V> node = first;
        while (node != null) {
            if (visit.visit(node.key, node.value)){
                return;
            }
            node = node.next;
        }
    }

    @Override
    public void afterRemoveFixLinkedMap(Node<K, V> willNode, Node<K, V> removeNode) {
        LinkedNode<K, V> node1 = (LinkedNode<K, V>) willNode;
        LinkedNode<K, V> node2 = (LinkedNode<K, V>) removeNode;
        if (node1 != node2) {
            LinkedNode<K, V> tmp1 = node1.prev;
            node1.prev = node2.prev;
            node2.prev = tmp1;
            if (node1.prev == null) {
                first = node1;
            } else {
                node1.prev.next = node1;
            }
            if (node2.prev == null) {
                first = node2;
            } else {
                node2.prev.next = node2;
            }
            LinkedNode<K, V> tmp2 = node1.next;
            if (node1.next == null) {
                last = node1;
            } else {
                node1.next.prev = node1;
            }
            if (node2.next == null) {
                last = node2;
            } else {
                node2.next.prev = node2;
            }
        }
        LinkedNode<K, V> prev = node2.prev;
        LinkedNode<K, V> next = node2.next;
        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
        }
        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
        }
    }

    @Override
    public Node<K, V> createNode(K key, V value, Node<K, V> parent) {
        LinkedNode<K, V> node = new LinkedNode<>(key, value, parent);
        if (first == null) {
            first = last = node;
        } else {
            last.next = node;
            node.prev = last;
            last = node;
        }
        return node;
    }

    public static class LinkedNode<K, V> extends Node<K, V> {

        LinkedNode<K, V> prev;

        LinkedNode<K, V> next;

        public LinkedNode(K key, V value, Node<K, V> parent) {
            super(key, value, parent);
        }
    }

    public static void main(String[] args) {
        Map<String, String> map = new LinkedHashMap<>();
        for (int i = 0; i < 100; i++) {
            map.put(i + "", i + "");
        }
        System.out.println(map.size());
        System.out.println(map.remove("2"));
        System.out.println(map.remove("200"));
        System.out.println(map.size());
        System.out.println(map.containsKey("3"));
        System.out.println(map.containsKey("2"));
    }
}
